// import com.alibaba.druid.sql.ast.SQLExpr;
// import com.alibaba.druid.sql.ast.SQLReplaceable;
// import com.alibaba.druid.sql.dialect.oracle.ast.OracleSQLObjectImpl;
// import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;

// import java.util.ArrayList;
// import java.util.List;

#include "OracleReturningClause.h"
#include "../../../../ast/SQLExpr.h"
#include "../../../../ast/SQLReplaceable.h"
#include "../../visitor/OracleASTVisitor.h"
#include "../../../../../utils/listTran.h"

SQLExpr_list_ptr OracleReturningClause::getItems()
{
  return items;
}

OracleReturningClause::OracleReturningClause()
{
  items = std::make_shared<std::list<SQLExpr_ptr>>();
  values = std::make_shared<std::list<SQLExpr_ptr>>();
}

void OracleReturningClause::addItem(SQLExpr_ptr item)
{
  if (item != nullptr)
  {
    item->setParent(SharedObject(OracleReturningClause));
  }
  this->items->push_back(item);
}

SQLExpr_list_ptr OracleReturningClause::getValues()
{
  return values;
}

void OracleReturningClause::addValue(SQLExpr_ptr value)
{
  if (value != nullptr)
  {
    value->setParent(SharedObject(OracleReturningClause));
  }
  this->values->push_back(value);
}

// @Override
void OracleReturningClause::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(OracleReturningClause)))
  {
    SQLObject_list_ptr tmp1 = ListTran::tran_class<SQLExpr, SQLObject>(items);
    acceptChild(visitor, tmp1);
    SQLObject_list_ptr tmp2 = ListTran::tran_class<SQLExpr, SQLObject>(values);
    acceptChild(visitor, tmp2);
  }
  visitor->endVisit(SharedObject(OracleReturningClause));
}

// @Override
SQLObject_ptr OracleReturningClause::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<OracleReturningClause>(new OracleReturningClause());
  std::shared_ptr<OracleReturningClause> x = std::dynamic_pointer_cast<OracleReturningClause>(clone_tmp);
  // OracleReturningClause x = new OracleReturningClause();

  for (SQLExpr_ptr item : *items)
  {
    SQLExpr_ptr item2 = std::dynamic_pointer_cast<SQLExpr>(item->clone());
    item2->setParent(x);
    x->items->push_back(item2);
  }

  for (SQLExpr_ptr v : *values)
  {
    SQLExpr_ptr v2 = std::dynamic_pointer_cast<SQLExpr>(v->clone());
    v2->setParent(x);
    x->values->push_back(v2);
  }

  return x;
}

// @Override
BOOL_ptr OracleReturningClause::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  auto it_items = items->begin();
  for (int i = items->size() - 1; i >= 0; i--)
  {
    auto it_items = items->begin();
    std::advance(it_items, i);
    if (*it_items == expr)
    {
      target->setParent(SharedObject(OracleReturningClause));
      *it_items = target;
      return BOOL::TRUE;
    }
  }

  auto it_values = values->begin();
  for (int i = values->size() - 1; i >= 0; i--)
  {
    std::advance(it_values, i);
    if (*it_values == expr)
    {
      target->setParent(SharedObject(OracleReturningClause));
      *it_values = target;
      return BOOL::TRUE;
    }
  }

  return BOOL::FALSE;
}
